package com.nekrashevych;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.nekrashevych.itm.GenerationTagLiterals;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaClass;

public class StringMergeUtil {

    /**
     * Removes from "toFetch" first entrance of "start" to "end" tag. In any
     * failure toFetch is returned <br/>
     * E.g. <code>remove("xx.YY.Z,zz,", ".", ",")</code> => xxZZ,<br/>
     * <code>remove("x.y", ".", ",")</code> => "x.y",<br/>
     */
    public static String remove(String toFetch, String start, String end) {
        int startIndex = StringUtils.indexOf(toFetch, start);
        if (startIndex < 0) {
            return toFetch;
        }
        int endIndex = StringUtils.indexOf(toFetch, end, startIndex);
        if (endIndex < 0) {
            return toFetch;
        }
        return StringUtils.remove(toFetch, StringUtils.substring(toFetch, startIndex, endIndex + end.length()));
    }

    /**
     * Inserts with new line in the end as insert method<br/>
     * 
     * @see StringMergeUtil#insert(String, String, String)
     */
    public static String insertLine(String toInsert, String beforeFirst, String insertion) {
        return insert(toInsert, beforeFirst, insertion + "\n");
    }

    /**
     * Inserts to "toInsert" "insertion" line before first entrance of
     * beforeFirst. In any failure "toInsert" is returned <br/>
     * E.g. <code>insert("abca", "a", "z")</code> => "zabca"<br/>
     * <code>remove("bc", "a", "z")</code> => "bc"<br/>
     */
    public static String insert(String toInsert, String beforeFirst, String insertion) {
        int startIndex = StringUtils.indexOf(toInsert, beforeFirst);
        if (startIndex < 0) {
            return toInsert;
        }
        return StringUtils.join(StringUtils.substringBefore(toInsert, beforeFirst), insertion, beforeFirst,
                StringUtils.substringAfter(toInsert, beforeFirst));
    }

    /**
     * "a,b,c" => "a","b","c"
     */
    public static String splitToArray(String str) {
        return "\"" + StringUtils.join(StringUtils.split(str, ","), "\", \"") + "\"";
    }

    /**
     * "x", "a", "b", null, "", "c" => "x","a","b","c"
     */
    public static String joinWithoutNulls(String separator, String... strings) {
        return joinWithoutNulls(Arrays.asList(strings), separator);
    }

    /**
     * "x", "a", "b", null, "", "c" => "x,a,b,c"
     */
    public static String joinWithoutNulls(Iterable<String> strings, String separator) {
        List<String> tmp = new ArrayList<String>();
        for (String o : strings) {
            if (StringUtils.isNotBlank(o)) {
                tmp.add(o);
            }
        }
        return StringUtils.join(tmp, separator);
    }

    /**
     * This method is copied from the hibernate native naming strategy to
     * compare column names. DON'T CHANGE THIS METHOD!
     */
    public static String toColumnUnderscores(String name) {
        StringBuilder buf = new StringBuilder(name.replace('.', '_'));
        for (int i = 1; i < buf.length() - 1; i++) {
            if (Character.isLowerCase(buf.charAt(i - 1)) && Character.isUpperCase(buf.charAt(i)) && Character.isLowerCase(buf.charAt(i + 1))) {
                buf.insert(i++, '_');
            }
        }
        return buf.toString().toLowerCase();
    }
}
